package com.fingard.dsp.bank.directbank.crbc01.util;

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;

import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

public class CrbankFileZip {

    public static final int BUFFER = 1024;// 缓存大小

    /**
     * 对单个文件进行压缩
     *
     * @param zipFilePath   需要压缩的文件路径
     * @param zipedFilePath 被压缩后保存的文件路径
     * @throws IOException
     */
    public static void zipFileWithFile(String zipFilePath, String zipedFilePath)
            throws IOException {
        zipFileWithFile(zipFilePath, zipedFilePath, BUFFER);
    }


    /**
     * 对单个文件进行压缩
     *
     * @param zipFilePath   需要压缩的文件路径
     * @param zipedFilePath 被压缩后保存的文件路径
     * @param bufferSize    指定压缩缓冲大小
     * @throws IOException
     */
    public static void zipFileWithFile(String zipFilePath, String zipedFilePath, int bufferSize) throws IOException {
        ZipOutputStream zos = null;
        BufferedInputStream is = null;
        FileInputStream fis = null;
        try {
            zos = new ZipOutputStream(new FileOutputStream(zipedFilePath));
            ZipEntry ze = null;
            int size = BUFFER;
            if (bufferSize > 0) {
                size = bufferSize;
            }
            byte[] buf = new byte[size];
            int readLen = 0;
            File f = new File(zipFilePath);
            ze = new ZipEntry(f.getName());
//        ze = new ZipEntry("2019012022203031692.txt");
//        ze.setSize(f.length());
            System.out.println(f.length());
            Long time = System.currentTimeMillis();
            System.out.println(time);
            ze.setTime(time);
//        ze.setTime(f.lastModified());
//        ze.setTime(1547995361824L);
            zos.putNextEntry(ze);
            fis = new FileInputStream(f);
            is = new BufferedInputStream(fis);
            while ((readLen = is.read(buf, 0, BUFFER)) != -1) {
                zos.write(buf, 0, readLen);
            }
            is.close();
            zos.flush();
            zos.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            if (zos != null) {
                zos.close();
            }
            if (is != null) {
                is.close();
            }
            if (fis != null) {
                fis.close();
            }
        }
    }

    public static ByteArrayOutputStream zipFileByMemory(String context, String fileName) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ZipOutputStream zos = new ZipOutputStream(baos);
        ZipEntry ze = new ZipEntry(fileName);
//        ze.setSize(context.length());
        long time = System.currentTimeMillis();
        ze.setTime(time);
        zos.putNextEntry(ze);
        zos.write(context.getBytes());
        zos.flush();
        zos.close();
        return baos;
    }

    /**
     * zip压缩功能. 压缩baseDir(文件夹目录)下所有文件，包括子目录
     *
     * @throws Exception
     */
    public static void zipFileWithDir(String baseDir, String zipedFileName) throws Exception {
        List fileList = getSubFiles(new File(baseDir));
        ZipOutputStream zos = null;
        InputStream is = null;
        FileOutputStream fos = null;
        FileInputStream fis = null;
        try {
            fos = new FileOutputStream(zipedFileName);
            zos = new ZipOutputStream(fos);
            ZipEntry ze = null;
            byte[] buf = new byte[BUFFER];
            int readLen = 0;
            for (int i = 0; i < fileList.size(); i++) {
                File f = (File) fileList.get(i);
                ze = new ZipEntry(getAbsFileName(baseDir, f));
                ze.setSize(f.length());
                ze.setTime(f.lastModified());
                zos.putNextEntry(ze);
                fis = new FileInputStream(f);
                is = new BufferedInputStream(fis);
                while ((readLen = is.read(buf, 0, BUFFER)) != -1) {
                    zos.write(buf, 0, readLen);
                }
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            if (zos != null) {
                zos.flush();
                zos.close();
            }
            if (fis != null) {
                fis.close();
            }
            if (fos != null) {
                fos.close();
            }
            if (is != null) {
                is.close();
            }
        }
    }

    /**
     * 给定根目录，返回另一个文件名的相对路径，用于zip文件中的路径.
     *
     * @param baseDir      java.lang.String 根目录
     * @param realFileName java.io.File 实际的文件名
     * @return 相对文件名
     */
    private static String getAbsFileName(String baseDir, File realFileName) {
        File real = realFileName;
        File base = new File(baseDir);
        String ret = real.getName();
        while (true) {
            real = real.getParentFile();
            if (real == null)
                break;
            if (real.equals(base))
                break;
            else
                ret = real.getName() + "/" + ret;
        }
        System.out.println(ret);
        return ret;
    }

    /**
     * 取得指定目录下的所有文件列表，包括子目录.
     *
     * @param baseDir File 指定的目录
     * @return 包含java.io.File的List
     */
    private static List getSubFiles(File baseDir) {
        List ret = new ArrayList();
        File[] tmp = baseDir.listFiles();
        for (int i = 0; i < tmp.length; i++) {
            if (tmp[i].isFile())
                ret.add(tmp[i]);
            if (tmp[i].isDirectory())
                ret.addAll(getSubFiles(tmp[i]));
        }
        return ret;
    }

    /**
     * 解压缩功能
     *
     * @param unZipFilePath 需要解压的文件路径
     * @param unZipFileDir  解压缩后文件的保存目录
     * @throws Exception
     */
    public static void upZipFile(String unZipFilePath, String unZipFileDir)
            throws Exception {
        ZipFile zfile = new ZipFile(unZipFilePath);
        Enumeration zList = zfile.getEntries();
        OutputStream os = null;
        ZipEntry ze = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            byte[] buf = new byte[1024];
            while (zList.hasMoreElements()) {
                ze = (ZipEntry) zList.nextElement();
                if (ze.isDirectory()) {
                    File f = new File(unZipFileDir + ze.getName());
                    f.mkdir();
                    continue;
                }
                fos = new FileOutputStream(getRealFileName(unZipFileDir, ze.getName()));
                os = new BufferedOutputStream(fos);
                is = new BufferedInputStream(zfile.getInputStream(ze));
                int readLen = 0;
                while ((readLen = is.read(buf, 0, 1024)) != -1) {
                    os.write(buf, 0, readLen);
                }
            }
            zfile.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            if (is != null) {
                is.close();
            }
            if (fos != null) {
                fos.close();
            }
            if (os != null) {
                os.close();
            }
        }
    }

    /**
     * 给定根目录，返回一个相对路径所对应的实际文件名.
     *
     * @param baseDir     指定根目录
     * @param absFileName 相对路径名，来自于ZipEntry中的name
     * @return java.io.File 实际的文件
     */
    public static File getRealFileName(String baseDir, String absFileName) {
        String[] dirs = absFileName.split("/");
        File ret = new File(baseDir);
        if (dirs.length > 1) {
            for (int i = 0; i < dirs.length - 1; i++) {
                ret = new File(ret, dirs[i]);
            }
            if (!ret.exists())
                ret.mkdirs();
            return ret;
        } else {
            ret = new File(ret, dirs[dirs.length - 1]);
        }
        return ret;
    }
}
